home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / ICMPCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-05  |  4.5 KB  |  193 lines

  1. /* ICMP-related user commands */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "icmp.h"
  5. #include "mbuf.h"
  6. #include "netuser.h"
  7. #include "internet.h"
  8. #include "timer.h"
  9. #include "socket.h"
  10. #include "proc.h"
  11. #include "session.h"
  12.  
  13. extern struct icmp_errors Icmp_errors;
  14. extern struct icmp_stats Icmp_stats;
  15. extern int32 Clock;
  16. extern char *Icmptypes[];
  17. char *inet_ntoa();
  18. struct mbuf *htonicmp();
  19. void pingtx();
  20. static int pingem();
  21.  
  22. int
  23. doicmpstat()
  24. {
  25.     register int i;
  26.  
  27.     printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
  28.      Icmp_errors.checksum,Icmp_errors.nospace,Icmp_errors.noloop,
  29.      Icmp_errors.bdcsts);
  30.     printf("type  rcvd  sent\n");
  31.     for(i=0;i<ICMP_TYPES;i++){
  32.         if(Icmp_stats.input[i] == 0 && Icmp_stats.output[i] == 0)
  33.             continue;
  34.         printf("%-6u%-6u%-6u",i,Icmp_stats.input[i],
  35.             Icmp_stats.output[i]);
  36.         if(Icmptypes[i] != NULLCHAR)
  37.             printf("  %s",Icmptypes[i]);
  38.         printf("\n");
  39.     }
  40.     return 0;
  41. }
  42.  
  43. /* Send ICMP Echo Request packets */
  44. doping(argc,argv)
  45. int argc;
  46. char *argv[];
  47. {
  48.     struct proc *pinger = NULLPROC;    /* Transmit process */
  49.     struct sockaddr_in to,from;
  50.     struct icmp icmp;
  51.     struct mbuf *bp;
  52.     struct session *sp;
  53.     int32 timestamp,rtt,abserr;
  54.     int s,fromlen;
  55.     struct ping ping;
  56.  
  57.     memset((char *)&ping,0,sizeof(ping));
  58.     /* Allocate a session descriptor */
  59.     if((sp = newsession(argv[1],PING)) == NULLSESSION){
  60.         printf("Too many sessions\n");
  61.         return 1;
  62.     }
  63.     sp->cb.ping = &ping;
  64.     ping.sp = sp;
  65.  
  66.     ping.proc = Curproc;
  67.     if((sp->s = s = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) == -1){
  68.         printf("Can't create socket\n");
  69.         freesession(sp);
  70.         return 1;
  71.     }
  72.     Current = sp;
  73.     Mode = CONV_MODE;
  74.     to.sin_family = AF_INET;
  75.     if((to.sin_addr.s_addr = resolve(argv[1])) == 0){
  76.         printf("Host %s unknown\n",argv[1]);
  77.         close_s(s);
  78.         freesession(sp);
  79.         return 1;
  80.     }
  81.     connect(s,(char *)&to,sizeof(to));
  82.  
  83.     if(argc > 2)
  84.         ping.len = atoi(argv[2]);
  85.  
  86.     if(argc > 3)
  87.         ping.interval = atoi(argv[3]);
  88.  
  89.     if(ping.interval != 0){
  90.         pinger = newproc("pingtx",300,pingtx,s,&ping,NULL);
  91.     } else {
  92.         ping.sent = 1;
  93.         pingem(s,0,(int16)Curproc,ping.len);
  94.     }
  95.     /* Now collect the replies */
  96.     for(;;){
  97.         fromlen = sizeof(from);
  98.         if(recv_mbuf(s,&bp,0,0,(char *)&from,&fromlen) == -1)
  99.             break;
  100.         ntohicmp(&icmp,&bp);
  101.         if(icmp.type != ECHO_REPLY
  102.          || from.sin_addr.s_addr != to.sin_addr.s_addr
  103.          || icmp.args.echo.id != (int16)Curproc){
  104.             /* Ignore other people's responses */
  105.             free_p(bp);
  106.             continue;
  107.         }
  108.         ping.responses++;
  109.         pullup(&bp,(char *)×tamp,sizeof(Clock));    /* Get stamp */
  110.         free_p(bp);
  111.  
  112.         /* Compute round trip time, update smoothed estimates */
  113.         rtt = (Clock - timestamp) * MSPTICK;
  114.         if(ping.interval == 0){
  115.             printf("%s: rtt %lu",sp->name,rtt);
  116.             break;
  117.         }
  118.         abserr = rtt > ping.srtt ? rtt - ping.srtt : ping.srtt - rtt;
  119.         if(ping.responses == 1){
  120.             /* First response, base entire SRTT on it */
  121.             ping.srtt = rtt;
  122.         } else {
  123.             ping.srtt = (7*ping.srtt + rtt + 4) >> 3;
  124.         }
  125.         ping.mdev = (3*ping.mdev + abserr + 2) >> 2;
  126.  
  127.     }
  128.     if(Current == sp && Mode == CONV_MODE)
  129.         printf("\n");
  130.     if(pinger != NULLPROC)
  131.         killproc(pinger);
  132.     close_s(s);
  133.     freesession(sp);
  134.     return 0;
  135. }
  136. /* Ping transmit process. Runs until killed */
  137. void
  138. pingtx(s,ping)
  139. int s;        /* Socket to use */
  140. struct ping *ping;
  141. {
  142.     long sdur;
  143.  
  144.     sdur = ping->interval * (1000 / MSPTICK);
  145.     ping->sent = 0;
  146.     for(;;){
  147.         if(Current == ping->sp && Mode == CONV_MODE){
  148.             printf("pinging %s: sent %lu rcvd %lu avg rtt %lu mdev %lu    \r",
  149.              ping->sp->name,ping->sent,ping->responses,ping->srtt,
  150.              ping->mdev);
  151.         }
  152.         pingem(s,(int16)ping->sent++,(int16)ping->proc,ping->len);
  153.         pause(sdur);
  154.     }
  155. }
  156.  
  157.  
  158. /* Send ICMP Echo Request packet */
  159. static
  160. pingem(s,seq,id,len)
  161. int s;        /* Raw socket on which to send ping */
  162. int16 seq;    /* ICMP Echo Request sequence number */
  163. int16 id;    /* ICMP Echo Request ID */
  164. int16 len;    /* Length of optional data field */
  165. {
  166.     struct mbuf *data = NULLBUF;
  167.     struct mbuf *bp;
  168.     struct icmp icmp;
  169.  
  170.     if((data = alloc_mbuf(len+sizeof(Clock))) == NULLBUF)
  171.         return -1;
  172.     data->cnt = len+sizeof(Clock);
  173.     /* Set optional data field, if any, to all 1's */
  174.     if(len != 0)
  175.         memset(data->data+sizeof(Clock),0xff,len);
  176.  
  177.     /* Insert timestamp and build ICMP header */
  178.     memcpy(data->data,(char *)&Clock,sizeof(Clock));
  179.     Icmp_stats.output[ECHO]++;
  180.     icmp.type = ECHO;
  181.     icmp.code = 0;
  182.     icmp.args.echo.seq = seq;
  183.     icmp.args.echo.id = id;
  184.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  185.         free_p(data);
  186.         return 0;
  187.     }
  188.     send_mbuf(s,bp,0,NULLCHAR,0);
  189.     return 0;
  190. }
  191.  
  192.  
  193.